
package com.onlyxiahui.wofa.server.socket.netty.tcp;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.onlyxiahui.framework.action.dispatcher.general.GeneralMessageHandler;
import com.onlyxiahui.wofa.server.net.core.Server;
import com.onlyxiahui.wofa.server.net.core.session.SocketSessionHandler;
import com.onlyxiahui.wofa.server.socket.netty.common.coder.NettyCodecCreater;
import com.onlyxiahui.wofa.server.socket.netty.common.coder.StringBytesCodec;
import com.onlyxiahui.wofa.server.socket.netty.tcp.impl.SocketServerInitializer;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.ssl.SslContext;

/**
 *
 * @author XiaHui
 */
public final class SocketServer implements Server {

	protected final Logger logger = LoggerFactory.getLogger(this.getClass());
	private int port = 12000;
	private ServerBootstrap server = new ServerBootstrap();
	private boolean start = false;
	private GeneralMessageHandler messageHandler;
	private SocketSessionHandler sessionHandler;
	private NettyCodecCreater coderCreater;
	private SslContext sslContext;

	public SocketServer(
			GeneralMessageHandler messageHandler,
			SocketSessionHandler sessionHandler) {
		this(messageHandler, sessionHandler, null);
	}

	public SocketServer(
			GeneralMessageHandler messageHandler,
			SocketSessionHandler sessionHandler,
			NettyCodecCreater coderCreater) {
		this(messageHandler, sessionHandler, coderCreater, null);
	}

	public SocketServer(
			GeneralMessageHandler messageHandler,
			SocketSessionHandler sessionHandler,
			NettyCodecCreater coderCreater,
			SslContext sslContext) {
		this.messageHandler = messageHandler;
		this.sessionHandler = sessionHandler;
		this.coderCreater = coderCreater == null ? (() -> new StringBytesCodec()) : coderCreater;
		this.sslContext = sslContext;
	}

	public boolean start(int port) {
		this.port = port;
		if (start) {
			return start;
		}
		EventLoopGroup bossGroup = new NioEventLoopGroup(1);
		EventLoopGroup workerGroup = new NioEventLoopGroup();
		try {
			start = true;
			server.group(bossGroup, workerGroup);
			server.channel(NioServerSocketChannel.class);
			server.handler(new LoggingHandler(LogLevel.INFO));
			server.childHandler(new SocketServerInitializer(messageHandler, sessionHandler, coderCreater, sslContext));
			Channel ch = server.bind(port).sync().channel();
			ch.closeFuture().sync();
		} catch (InterruptedException ex) {
			start = false;
			logger.error("SocketServer启动失败", ex);
		} finally {
			bossGroup.shutdownGracefully();
			workerGroup.shutdownGracefully();
		}
		return start;
	}

	public int getPort() {
		return port;
	}
}
